package fileby.gui;


import com.google.inject.Inject;
import com.google.inject.Singleton;

import fileby.util.properties.IPropertyBundleProvider;
import fileby.util.properties.PropertyBundle;
import fileby.core.ActionKey;
import fileby.core.IDisplayableFileSource;
import fileby.core.SourceType;
import fileby.core.UpdateEvent;
import fileby.ctrl.actions.IActionProvider;
import fileby.gui.breadcrumbs.BreadCrumbsPanel;
import fileby.gui.magicbox.MagicBox;
import fileby.gui.misc.FilebyAboutBox;
import fileby.gui.misc.SearchBox;
import fileby.gui.sidebar.ISideBarProvider;
import fileby.gui.tabs.TabPanel;
import fileby.util.plugins.Plugin;
import fileby.util.IObservable;

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.net.URL;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu.Separator;

/**
 * The application's main frame.
 */
@Singleton
public class MainFrame extends JFrame implements PropertyChangeListener {

    private IPropertyBundleProvider propertyProvider;
    private IActionProvider actionProvider;
    private ISideBarProvider sideBarProvider;
    private String titlePrefix;

    @Inject
    public MainFrame(IObservable observable, IPropertyBundleProvider p, IActionProvider a,
            ISideBarProvider sideBarProvider,
            MagicBox magicBox, TabPanel tabPanel, SearchBox searchBox,
            BreadCrumbsPanel breadCrumbsPanel, FilebyAboutBox aboutBox) {

        observable.addPropertyChangeListener(this);

        this.sideBarProvider = sideBarProvider;
        this.breadCrumbsPanel = breadCrumbsPanel;
        this.magicBox = magicBox;
        this.tabPanel = tabPanel;
        this.searchBox = searchBox;
        this.aboutBox = aboutBox;
        this.propertyProvider = p;
        this.actionProvider = a;
        initComponents();
        initCtrl();
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        switch (UpdateEvent.valueOf(evt.getPropertyName())) {
            case SOURCE_CHANGE:
                if (evt.getNewValue() == null) {
                    tabPanel.closeTab((Integer) evt.getOldValue());
                } else if (evt.getOldValue() == null) {
                    tabPanel.addNewTab((IDisplayableFileSource) evt.getNewValue());
                } else {
                    tabPanel.changeTab((IDisplayableFileSource) evt.getOldValue(),
                            (IDisplayableFileSource) evt.getNewValue());
                }
                break;

            case CONTENT_CHANGE:
                tabPanel.updateTab((IDisplayableFileSource) evt.getNewValue());
                break;

            case FAVORITES_CHANGE:
                favoritePanel.updateSidebarItems(((IDisplayableFileSource) evt.getNewValue()).getFiles());
                break;

            case CURRENT_SOURCE_CHANGE:
                searchBox.setText(((IDisplayableFileSource) evt.getNewValue()).getName());
                breadCrumbsPanel.update((IDisplayableFileSource) evt.getNewValue());
                setTitle(titlePrefix + ((IDisplayableFileSource) evt.getNewValue()).getName());
                break;

            case DEVICES_CHANGE:
                devicePanel.updateSidebarItems(((IDisplayableFileSource) evt.getNewValue()).getFiles());
                break;

            case ERROR_OCCURRENCE:
                JOptionPane.showMessageDialog(null, evt.getNewValue(), "Something bad has happened!", JOptionPane.ERROR_MESSAGE);
                break;

            case MAGIC_BOX_CHANGE:
                if (evt.getNewValue() instanceof Plugin) {
                    magicBox.setPlugin((Plugin) evt.getNewValue());
                } else if (evt.getNewValue() instanceof IDisplayableFileSource) {
                    magicBox.updateItem(((IDisplayableFileSource) evt.getNewValue()).getFiles());
                }
                break;

            default:
                System.err.println("Update Event not captured: " + evt.getPropertyName());
        }
    }

    private void initCtrl() {
        initMenuCtrl();
        setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
        addWindowListener(new WindowAdapter() {

            @Override
            public void windowOpened(WindowEvent e) {
                requestFocusInWindow();
            }

            @Override
            public void windowClosing(WindowEvent e) {
                actionProvider.getControl(ActionKey.QUIT).actionPerformed(null);
            }
        });
    }

    private void initMenuCtrl() {
        fileMenu.add(new JMenuItem(actionProvider.getControl(ActionKey.NEW_TAB)));
        fileMenu.add(new JMenuItem(actionProvider.getControl(ActionKey.CLOSE_ACTIVE_TAB)));
        fileMenu.add(new JMenuItem(actionProvider.getControl(ActionKey.CREATE_FOLDER)));
        fileMenu.add(new Separator());
        fileMenu.add(new JMenuItem(actionProvider.getControl(ActionKey.QUIT)));

        editMenu.add(new JMenuItem(actionProvider.getControl(ActionKey.OPEN)));
        editMenu.add(new JMenuItem(actionProvider.getControl(ActionKey.OPEN_IN_NEW_TAB)));
        editMenu.add(new Separator());
        editMenu.add(new JMenuItem(actionProvider.getControl(ActionKey.CUT)));
        editMenu.add(new JMenuItem(actionProvider.getControl(ActionKey.COPY)));
        editMenu.add(new JMenuItem(actionProvider.getControl(ActionKey.PASTE)));
        editMenu.add(new JMenuItem(actionProvider.getControl(ActionKey.DELETE)));
        editMenu.add(new Separator());
        editMenu.add(new JMenuItem(actionProvider.getControl(ActionKey.SELECT_ALL)));

        Action aboutBoxAction = actionProvider.getControl(ActionKey.SHOW_ABOUT_BOX);
        helpMenu.add(new JMenuItem(aboutBoxAction));
        aboutBoxAction.putValue(ActionKey.SHOW_ABOUT_BOX.toString(), aboutBox);
        aboutBoxAction.putValue("Parent", this);

        //Possibly a pretty ugly solution, have to set parent (Frame) for JFilechooser
        //that appears when load plugin button is pressed in MagicBox.
        Action loadPlugin = actionProvider.getControl(ActionKey.LOAD_PLUGIN);
        loadPlugin.putValue("Parent", this);
    }

    // <editor-fold defaultstate="collapsed" desc="Used to be generated code">
    private void initComponents() {

        menuBar = new javax.swing.JMenuBar();
        fileMenu = new javax.swing.JMenu();
        editMenu = new javax.swing.JMenu();
        helpMenu = new javax.swing.JMenu();
        contents = new javax.swing.JPanel();

        favoritePanel = sideBarProvider.createPanel(SourceType.FAVORITE);
        devicePanel = sideBarProvider.createPanel(SourceType.COMPUTER);

        PropertyBundle bundle = propertyProvider.create(this.getClass());

        fileMenu.setText(bundle.getString("fileMenu.text")); // NOI18N
        menuBar.add(fileMenu);

        editMenu.setText(bundle.getString("editMenu.text")); // NOI18N
        menuBar.add(editMenu);

        helpMenu.setText(bundle.getString("helpMenu.text")); // NOI18N
        menuBar.add(helpMenu);

        contents.setBackground(propertyProvider.createGlobalBundle().getColor("background.color")); // NOI18N

        breadCrumbsPanel.setBackground(bundle.getColor("breadCrumbsPanel1.background")); // NOI18N
        breadCrumbsPanel.setOpaque(false);
        breadCrumbsPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 3, 1));

        magicBox.setMinimumSize(new java.awt.Dimension(200, 150));

        favoritePanel.setBackground(bundle.getColor("favoritePanel.background")); // NOI18N
        favoritePanel.setMinimumSize(new java.awt.Dimension(200, 100));

        devicePanel.setBackground(bundle.getColor("devicePanel.background")); // NOI18N
        devicePanel.setMaximumSize(new java.awt.Dimension(200, 32767));
        devicePanel.setMinimumSize(new java.awt.Dimension(200, 65));

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(contents);
        contents.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
                jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(jPanel1Layout.createSequentialGroup().addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addComponent(devicePanel, javax.swing.GroupLayout.PREFERRED_SIZE, 200, javax.swing.GroupLayout.PREFERRED_SIZE).addComponent(favoritePanel, javax.swing.GroupLayout.PREFERRED_SIZE, 200, javax.swing.GroupLayout.PREFERRED_SIZE).addComponent(magicBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addComponent(tabPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 593, Short.MAX_VALUE)).addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup().addContainerGap().addComponent(breadCrumbsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 602, Short.MAX_VALUE).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addComponent(searchBox, javax.swing.GroupLayout.PREFERRED_SIZE, 171, javax.swing.GroupLayout.PREFERRED_SIZE).addContainerGap()));
        jPanel1Layout.setVerticalGroup(
                jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(jPanel1Layout.createSequentialGroup().addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(jPanel1Layout.createSequentialGroup().addGap(11, 11, 11).addComponent(breadCrumbsPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE)).addGroup(jPanel1Layout.createSequentialGroup().addGap(15, 15, 15).addComponent(searchBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING).addGroup(jPanel1Layout.createSequentialGroup().addComponent(devicePanel, javax.swing.GroupLayout.DEFAULT_SIZE, 65, Short.MAX_VALUE).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addComponent(favoritePanel, javax.swing.GroupLayout.DEFAULT_SIZE, 100, Short.MAX_VALUE).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addComponent(magicBox, javax.swing.GroupLayout.DEFAULT_SIZE, 279, Short.MAX_VALUE)).addComponent(tabPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 456, Short.MAX_VALUE))));
        URL u = this.getClass().getResource(bundle.getString("window.icon"));
        setIconImage(new ImageIcon(u).getImage());
        setContentPane(contents);
        setJMenuBar(menuBar);
        titlePrefix = bundle.getString("titlePrefix.text");
        setTitle(titlePrefix);
        setVisible(true);
        pack();

    }// </editor-fold>
    private fileby.gui.breadcrumbs.BreadCrumbsPanel breadCrumbsPanel;
    private fileby.gui.sidebar.SideBarPanel devicePanel;
    private javax.swing.JMenu fileMenu;
    private javax.swing.JMenu editMenu;
    private javax.swing.JMenu helpMenu;
    private fileby.gui.sidebar.SideBarPanel favoritePanel;
    private javax.swing.JPanel contents;
    private fileby.gui.magicbox.MagicBox magicBox;
    private javax.swing.JMenuBar menuBar;
    private fileby.gui.misc.SearchBox searchBox;
    private fileby.gui.tabs.TabPanel tabPanel;
    private FilebyAboutBox aboutBox;
}
